//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2007
//
// Toolbar control.
//

# include "StdAfx.h"
# include "Resource.h"
# include "Toolbar.h"
# include "Menu.h"
# include "Status.h"
# include "Scale.h"
# include "ParseHelpers.h"
# include "Globals.h"

HWND g_hToolbarWnd;
HWND g_hToolbarTipWnd;

HWND g_hScaleCB;
HWND g_hScaleEB;

static WNDPROC g_wpScaleEdit = NULL;
LRESULT APIENTRY _ScaleEditProc (HWND _hWnd, UINT _uMsg, WPARAM _wParam, LPARAM _lParam);

bool InitToolbar () {
	assert (g_hWnd);

	const TBBUTTON btns [] = {
		{0,  ID_FILE_ADD,             TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{1,  ID_FILE_SAVE,            TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{2,  ID_FILE_CLOSE,           TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},

		{0,  -1,                      TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0},
//		{3,  ID_FILE_PRINT,           TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{4,  ID_MAP_PROPERTIES,       TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{5,  ID_EDIT_PAI,             TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{6,  ID_WTR,                  TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},

		{0,  -1,                      TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0},
		{7,  ID_GPS_TRACKING,         TBSTATE_ENABLED, TBSTYLE_CHECK,  0, 0},

		{0,  -1,                      TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0},
		{8,  ID_TOOL_DRAG,            TBSTATE_ENABLED, TBSTYLE_GROUP,  0, 0},
		{9,  ID_TOOL_ZOOM,            TBSTATE_ENABLED, TBSTYLE_GROUP,  0, 0},
		{10, ID_TOOL_SELECT,          TBSTATE_ENABLED, TBSTYLE_GROUP,  0, 0},
		{11, ID_TOOL_EDIT_NODES,      TBSTATE_ENABLED, TBSTYLE_GROUP,  0, 0},
		{12, ID_TOOL_CREATE_RGN,      TBSTATE_ENABLED, TBSTYLE_GROUP | TBSTYLE_DROPDOWN, 0, 0},
		{13, ID_TOOL_TRIM,            TBSTATE_ENABLED, TBSTYLE_GROUP,  0, 0},
		{14, ID_TOOL_TRANSFORM,       TBSTATE_ENABLED, TBSTYLE_GROUP | TBSTYLE_DROPDOWN, 0, 0},
		{15, ID_TOOL_ROUTING,         TBSTATE_ENABLED, TBSTYLE_GROUP,  0, 0},

		{0,  -1,                      TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0},
		// NOTE: this is just the placeholder for the 'scales' combobox
		// which will be placed above.
		{0,  ID_SCALES_CB,            TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0},
		{16, ID_ZOOM_IN,              TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{17, ID_ZOOM_OUT,             TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},

		{0,  -1,                      TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0},
		{18, ID_SHOW_LABELS,          TBSTATE_ENABLED, TBSTYLE_CHECK,  0, 0},
		{19, ID_SHOW_RULER,           TBSTATE_ENABLED, TBSTYLE_CHECK,  0, 0},
		{20, ID_SHOW_GRID,            TBSTATE_ENABLED, TBSTYLE_CHECK,  0, 0},
		{21, ID_TRANSPARENT_POLYGONS, TBSTATE_ENABLED, TBSTYLE_CHECK,  0, 0},
		{22, ID_SHOW_RGNODES,         TBSTATE_ENABLED, TBSTYLE_CHECK,  0, 0},
		{23, ID_SHOW_ROAD_CLASSES,    TBSTATE_ENABLED, TBSTYLE_CHECK,  0, 0},
		{24, ID_HIGHLIGHT_ADDRESSES,  TBSTATE_ENABLED, TBSTYLE_CHECK,  0, 0},
		{25, ID_SHOW_ATTACHMENTS,     TBSTATE_ENABLED, TBSTYLE_CHECK,  0, 0},
		{26, ID_SHOW_GOOGLEMAPS,      TBSTATE_ENABLED, TBSTYLE_CHECK,  0, 0},

		{0,  -1,                      TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0},
		{27, ID_EDIT_UNDO,            TBSTATE_ENABLED, TBSTYLE_DROPDOWN, 0, 0},
		{28, ID_EDIT_REDO,            TBSTATE_ENABLED, TBSTYLE_DROPDOWN, 0, 0},

		{0,  -1,                      TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0},
		{29, ID_EDIT_CUT,             TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{30, ID_EDIT_COPY,            TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{31, ID_EDIT_PASTE,           TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{32, ID_EDIT_DELETE,          TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
	};
	g_hToolbarWnd = ::CreateToolbarEx (
		g_hWnd, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | CCS_TOP | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS, 100,
		30, g_hInst, IDT_TOOLBAR,
		btns, ARRAY_SIZE (btns), 0, 0, 16, 16, sizeof (TBBUTTON)
	);
	// Enable downarrows for Undo/Redo.
	::SendMessage (g_hToolbarWnd, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS);

	g_hToolbarTipWnd = reinterpret_cast<HWND> (::SendMessage (g_hToolbarWnd, TB_GETTOOLTIPS, 0, 0));

	g_MainMenu.SetToolbar (g_hToolbarWnd);

	//
	// Add 'scale' combobox.
	//

	const size_t cBtnIndex = ::SendMessage (g_hToolbarWnd, TB_COMMANDTOINDEX, ID_SCALES_CB, 0);
	if (! g_bNT) {
		// NOTE: combobox' behaviour appears unpredictable under Win9x (up to system crash).
		::SendMessage (g_hToolbarWnd, TB_DELETEBUTTON, cBtnIndex, 0);
		return true;
	}

	RECT rectCB;
	::SendMessage (g_hToolbarWnd, TB_GETITEMRECT, cBtnIndex, reinterpret_cast<LPARAM> (& rectCB));

	const WORD wHBaseUnit = LOWORD (::GetDialogBaseUnits ());

	g_hScaleCB = ::CreateWindow (
		WC_COMBOBOXEX, NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_CLIPSIBLINGS | CBS_DROPDOWN,
		rectCB.left, 1, ::MulDiv (70, wHBaseUnit, 8), 600,
		g_hToolbarWnd, (HMENU) ID_SCALES_CB, g_hInst, NULL
	);
	::SendMessage (g_hScaleCB, CBEM_SETEXTENDEDSTYLE, CBES_EX_NOEDITIMAGE, CBES_EX_NOEDITIMAGE);
	::SendMessage (g_hScaleCB, WM_SETFONT, (WPARAM) ::GetStockObject (DEFAULT_GUI_FONT), FALSE);

	// Change width of separator on the toolbar being below the scales combobox.
	::GetWindowRect (g_hScaleCB, & rectCB);
	TBBUTTONINFO bi;
	bi.cbSize = sizeof (bi);
    bi.dwMask = TBIF_SIZE;
	bi.cx     = rectCB.right - rectCB.left;
	::SendMessage (g_hToolbarWnd, TB_SETBUTTONINFO, ID_SCALES_CB, reinterpret_cast<LPARAM> (& bi));

	// Get the edit box.
	g_hScaleEB = (HWND) ::SendMessage (g_hScaleCB, CBEM_GETEDITCONTROL, 0, 0);
	::SendMessage (g_hScaleEB, EM_SETMARGINS, EC_LEFTMARGIN, 3);

	// Fill combobox' list with scales menu items.
	const size_t cStdScales = GetStdScales ();
	for (size_t cStdScale = 0; cStdScale < cStdScales; ++ cStdScale) {
		char strScaleText [64];
		const bool bText = GetStdScaleName (cStdScale, strScaleText);
		if (! bText)
			continue;

		COMBOBOXEXITEM cbi;
		cbi.mask       = CBEIF_TEXT | CBEIF_LPARAM;
		cbi.iItem      = -1;
		cbi.pszText    = strScaleText;
		cbi.cchTextMax = sizeof (strScaleText);
		cbi.lParam     = ID_VIEW_SCALE_0 + cStdScale;
		::SendMessage (g_hScaleCB, CBEM_INSERTITEM, 0, (LPARAM) & cbi);
	}

	// Subclass the edit box to hook ENTER and ESC.
	g_wpScaleEdit = reinterpret_cast<WNDPROC> (::GetWindowLong (g_hScaleEB, GWL_WNDPROC));
	::SetWindowLong (g_hScaleEB, GWL_WNDPROC, reinterpret_cast<long> (_ScaleEditProc));

	return true;
}

void DestroyToolbar () {
	// TODO:
}

static
void _OnEditScaleComplete (bool _bDone = true) {
	if (! g_bDialogMode)
		return;
	g_bDialogMode = false;

	// Return keyboard input from the Scale combo-box.
	::SetFocus (g_hWnd);

	if (_bDone) {
		char strScale [64];
		::GetWindowText (g_hScaleEB, strScale, sizeof (strScale));

		const char * p = NULL;
		float fScale = 0;
		if (ParseReal (strScale, strScale + ::strlen (strScale), & p, fScale) && fScale != 0) {
			if (p != NULL && * p != '\0') {
				// Omit spaces.
				while (* p == ' ')
					++ p;
				const char * const strUnit = p;
				while (* p != ' ' && * p != '\0')
					++ p;
				const size_t cUnitLen = p - strUnit;

				const float fRulerLen = GetRulerLen ();

				// Check unit.
				const char * const str_km = GetStr (IDS_UNIT_KM);
				if (cUnitLen == ::strlen (str_km)    && ::_strnicmp (strUnit, str_km,    cUnitLen) == 0) {
					SetScale (fScale*1000/fRulerLen);
					return;
				}

				const char * const str_m = GetStr (IDS_UNIT_M);
				if (cUnitLen == ::strlen (str_m)     && ::_strnicmp (strUnit, str_m,     cUnitLen) == 0) {
					SetScale (fScale/fRulerLen);
					return;
				}

				const char * const str_nmile = GetStr (IDS_UNIT_NMILE);
				if (cUnitLen == ::strlen (str_nmile) && ::_strnicmp (strUnit, str_nmile, cUnitLen) == 0) {
					SetScale (fScale*c_m_per_nmile/fRulerLen);
					return;
				}

				const char * const str_smile = GetStr (IDS_UNIT_SMILE);
				if (cUnitLen == ::strlen (str_smile) && ::_strnicmp (strUnit, str_smile, cUnitLen) == 0) {
					SetScale (fScale*c_m_per_smile/fRulerLen);
					return;
				}

				const char * const str_ft = GetStr (IDS_UNIT_FT);
				if (cUnitLen == ::strlen (str_ft)    && ::_strnicmp (strUnit, str_ft,    cUnitLen) == 0) {
					SetScale (fScale/c_feet_per_m/fRulerLen);
					return;
				}
			}
		}
	}

	// Restore scale text.
	SetScaleStatus (g_fScale);
}

static
LRESULT APIENTRY _ScaleEditProc (HWND _hWnd, UINT _uMsg, WPARAM _wParam, LPARAM _lParam) {
	switch (_uMsg) {
		case WM_SETFOCUS:
			g_bDialogMode = true;
			break;

		case WM_KILLFOCUS:
			_OnEditScaleComplete ();
			break;

		case WM_CHAR:
			switch (_wParam) {
				case VK_RETURN: _OnEditScaleComplete (); break;
				case VK_ESCAPE: _OnEditScaleComplete (false); break;
			}
			break;
	}
		
	return ::CallWindowProc (g_wpScaleEdit, _hWnd, _uMsg, _wParam, _lParam);
}

